#! /usr/bin/env python
#
# Copyright 2008 Spencer Davis <SpencerDavis91@gmail.com>
#
# Tuxedo is a simple todo list application for GNOME.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://gnu.org/licenses/.>
#

import os
import sys
import locale
import gtk
import task
import pango
import gtk.glade
import statusconfig
from datetime import date
from task import Task
from config import Config
from database import Database
from adddialog import AddDialog
from editdialog import EditDialog
from aboutdialog import AboutDialog
from configdialog import ConfigDialog

class MainWindow:
    """Manages the main Tuxedo window"""
    def onAdd(self, obj):
        """Creates the dialog for adding a task."""
        # Create and run the dialog for adding a new task
        add = AddDialog(self.db)
        add.dialog.run()

        # Refresh the list
        self.refresh()

    def onEdit(self, obj):
        """Creates the dialog for editing the currently selected task."""

        # Get the selected row from the TreeView
        model, iter = self.taskView.get_selection().get_selected()

        # Get the task ID from treeview and use that to lookup task in database
        t = self.db.tasksdict[model.get_value(iter, 3)]

        # Create and run the dialog for editing the currently selected task
        edit = EditDialog(self.db, t)
        edit.dialog.run()

        # Refresh the list
        self.refresh()

    def onDelete(self, obj):
        """Deletes the currently selected task"""

        # Get the selected row from the TreeView
        model, iter = self.taskView.get_selection().get_selected()

        # Get the task ID from treeview and use that to lookup task in database
        t = self.db.tasksdict[model.get_value(iter, 3)]

        # Delete the task from the database
        self.db.deleteTask(t)

        # Refresh the list
        self.refresh()

    def onNotStarted(self, obj):
        """Changes the status of the currently selected task to Not Started"""

        # Get the selected row from the TreeView
        model, iter = self.taskView.get_selection().get_selected()

        # Get the task ID from treeview and use that to lookup task in database
        t = self.db.tasksdict[model.get_value(iter, 3)]

        # Set the task status as Not Started
        t.status = task.TASK_NOTSTARTED

        # Save the task
        self.db.saveTask(t)

        # Refresh the list
        self.refresh()

    def onInProgress(self, obj):
        """Changes the status of the currently selected task to In Progress"""

        # Get the selected row from the TreeView
        model, iter = self.taskView.get_selection().get_selected()

        # Get the task ID from treeview and use that to lookup task in database
        t = self.db.tasksdict[model.get_value(iter, 3)]

        # Set the task status as Not Started
        t.status = task.TASK_INPROGRESS

        # Save the task
        self.db.saveTask(t)

        # Refresh the list
        self.refresh()

    def onCompleted(self, obj):
        """Changes the status of the currently selected task to Completed"""

        # Get the selected row from the TreeView
        model, iter = self.taskView.get_selection().get_selected()

        # Get the task ID from treeview and use that to lookup task in database
        t = self.db.tasksdict[model.get_value(iter, 3)]

        # Set the task status as Completed
        t.status = task.TASK_COMPLETED

        # Save the task
        self.db.saveTask(t)

        # Refresh the list
        self.refresh()

    def onRefresh(self, obj):
        """Calls refresh to refresh the list of tasks."""
        self.refresh()

    def onAbout(self, obj):
        """Creates the about dialog when the about button is pressed."""
        # Show the About dialog
        about = AboutDialog()
        about.dialog.run()

    def onPreferences(self, obj):
        """Creates the configuration dialog."""
        # Show the config dialog
        config = ConfigDialog()
        config.dialog.run()

        # Refresh the list
        self.refresh()

    def onRowClick(self, treeView, path, column):
        """Opens the edit dialog when a task is double clicked"""
        # Call onEdit to open the edit dialog
        self.onEdit(None)

    def onQuit(self, obj):
        """Calls Destroy when the quit button is pressed."""
        self.destroy()

    def onClose(self, obj):
        """Closes main window but does not destroy it."""
        self.window.hide()

    def destroy(self, obj = None):
        """Quits the program."""
        gtk.main_quit()

    def showHideMainWindow(self, statusIcon):
        """If window is visible, hide it. If not, show it."""
        # If the main window is visible, hide it and remember its size and position
        if self.window.window.is_visible():
            self.size = self.window.get_size()
            self.position = self.window.get_position()
            self.window.window.hide()

        # If it is not visible, show it and move it to its original size and position
        else:
            self.window.window.show()
            self.window.show_all()
            self.window.move(self.position[0], self.position[1])
            self.window.resize(self.size[0], self.size[1])

    def refresh(self):
        """Refreshes the list of tasks"""
        # Clear the current list of tasks
        self.tasklist.clear()

        # Read all of the tasks from the database
        tasks = self.db.readTasks()

        # Append tasks to the ListStore
        for t in tasks:
            if sys.platform == 'linux2':
                localdate = date(t.duedate[0], t.duedate[1]+1, t.duedate[2]).strftime(locale.nl_langinfo(locale.D_FMT))
            else:
                localdate = date(t.duedate[0], t.duedate[1]+1, t.duedate[2]).strftime('%d %b %Y')
            self.tasklist.append([t.name + ' (' + localdate + ')', t.priority, t.status, t.id])

    def taskViewProperties(self, column, cell, model, iter, user_data):
        """Set display effects depending on task properties"""

        config = Config()
        prioritycolors = config.priorityColors()
        textcolors = config.textColors()
        statusoptions = config.statusOptions()

        # Set the background color and foreground color depending on the task priority
        priority = model.get_value(iter, 1)
        cell.set_property('background', prioritycolors[priority])
        cell.set_property('foreground', textcolors[priority])


        # Set the text style options depending on the task status and the settings
        status = model.get_value(iter, 2)
        # Bold weight or normal weight
        if statusoptions[status][statusconfig.STATUS_BOLD] is True:
            cell.set_property('weight', 700)
        else:
            cell.set_property('weight', 400)
        # Italic or normal
        if statusoptions[status][statusconfig.STATUS_ITALIC] is True:
            cell.set_property('style', pango.STYLE_ITALIC)
        else:
            cell.set_property('style', pango.STYLE_NORMAL)
        # Maybe underlined and maybe strikethrough
        cell.set_property('underline', statusoptions[status][statusconfig.STATUS_UNDERLINE])
        cell.set_property('strikethrough', statusoptions[status][statusconfig.STATUS_STRIKETHROUGH])

    def __init__(self, db):
        """Creates and displays the main window.""" 
        # Store the database connection that was passed
        self.db = db

        # Set the correct path for the glade file
        gladefile = os.path.join(os.path.dirname(sys.argv[0]), 'MainWindow.glade')

        # Get widgets from the glade file
        self.widgets = gtk.glade.XML(gladefile)

        # Store the signals in a dictionary
        signals = {'on_Add' : self.onAdd,
                   'on_Edit' : self.onEdit,
                   'on_Delete' : self.onDelete,
                   'on_Refresh' : self.onRefresh,
                   'on_Preferences' : self.onPreferences,
                   'on_RowActivated' : self.onRowClick,
                   'on_Quit' : self.onQuit,
                   'on_Close' : self.onClose,
                   'on_About' : self.onAbout}

        # Autoconnect the signals
        self.widgets.signal_autoconnect(signals)

        # Store the window widget
        self.window = self.widgets.get_widget('MainWindow')

        # Put correct values in Task / Change Status
        config = Config()
        # Get status menu item
        status = self.widgets.get_widget('Status')
        # Make a submenu
        statusmenu = gtk.Menu()
        status.set_submenu (statusmenu)
        statusmenu.show()
        # Make a menu item for each status
        notstarted = gtk.MenuItem (config.statusNames()[task.TASK_NOTSTARTED], True)
        inprogress = gtk.MenuItem (config.statusNames()[task.TASK_INPROGRESS], True)
        completed = gtk.MenuItem (config.statusNames()[task.TASK_COMPLETED], True)
        # Add them to their menu
        statusmenu.append (notstarted)
        statusmenu.append (inprogress)
        statusmenu.append (completed)
        # Connect them to their appropriate handlers
        notstarted.connect ('activate', self.onNotStarted)
        inprogress.connect ('activate', self.onInProgress)
        completed.connect ('activate', self.onCompleted)
        # Show them
        notstarted.show()
        inprogress.show()
        completed.show()

        # Tell the window not to delete itself when it's hidden
        self.window.connect('delete_event', self.window.hide_on_delete)

        # Start the position in the top right corner
        self.position = [self.window.get_screen().get_width(), 0]
        self.window.move(self.position[0], self.position[1])

        # Create a ListStore to store the tasks in
        self.tasklist = gtk.ListStore(str, int, int, int)

        # Set the TreeView to use the ListStore
        self.widgets.get_widget('TaskView').set_model(self.tasklist)

        # Create a text renderer
        self.cell = gtk.CellRendererText()

        # Create a column for the tasks
        self.taskcolumn = gtk.TreeViewColumn('Task', self.cell, text=0)

        # Store the Tree view
        self.taskView = self.widgets.get_widget('TaskView')

        # Add the column to the TreeView
        self.taskView.append_column(self.taskcolumn)

        # Call taskViewProperties to set up the different styles for the tasks
        self.taskcolumn.set_cell_data_func(self.cell, self.taskViewProperties, None)

